import * as koa from 'koa2';
import * as cors from 'koa2-cors';
import * as Router from 'koa-router';
import Roommgr from './roommgr';
import Http from '../utils/http';
import { httpRouterMap } from '../configs_win';
import Crypto from '../utils/crypto';
import TokenMgr from './tokenmgr';




const callPth = 'game_server->http_service.ts->'
const app = new koa();
const router = new Router();
app.use(cors());
app.use(router.routes()).use(router.allowedMethods());
/**游戏服务器配置信息 */
let config: game_server = null;
/**本服务器的信息(会被循环定时发送给房间管理服务器【room_service.ts】，房间管理服务器会把他存到一个数组里面，然后有新用户需要进入游戏的时候，循环遍历数组找到建立房间最少的服务器然后连接游戏) */
let gameServerInfo: gameServerInfoType = null;
let lastTickTime = 0;
let serverIp;


export default class Http_service{
    /**开启游戏的http服务器 */
    static start(_config: game_server){
        config = _config;
        gameServerInfo = {
            id: config.SERVER_ID,
            clientIp: config.CLIENT_IP,
            clientPort: config.CLIENT_PORT,
            httpPort: config.HTTP_PORT,
            load: Roommgr.getTotalRooms(),
        };

        setInterval(update, 1000);
        app.listen(config.HTTP_PORT, config.FOR_ROOM_IP, () => {
            console.log('游戏http服务器运行在:' + config.FOR_ROOM_IP + ':' + config.HTTP_PORT);
        });
    }
}








router.get(httpRouterMap.CREATE_ROOM,       create_room);
router.get(httpRouterMap.ENTER_ROOM,        enter_room);
router.get(httpRouterMap.IS_ROOM_RUNING,    is_room_runing);













/**
 * 创建房间
 * @param ctx 
 */
async function create_room(ctx: Router.IRouterContext){
    const userId = parseInt(ctx.query.userId);
    const sign = ctx.query.sign;
    const gems = ctx.query.gems;
    let conf = ctx.query.conf;
    if(userId == null || sign == null || conf == null){
        Http.send(ctx, 1, callPth + 'create_room->:userId == null || sign == null || conf == null');
        return;
    }

    const signMd5 = Crypto.md5(userId.toString() + conf + gems + config.ROOM_PRI_KEY);
    if(signMd5 != sign){
        Http.send(ctx, 1, callPth + 'create_room->:sign验签失败');
        return;
    }

    conf = JSON.parse(<string>conf);
    const data = await Roommgr.createRoom(userId, conf, gems, serverIp, config.CLIENT_PORT);
    if(data.errcode == 0){
        Http.send(ctx, data.errcode, 'ok', {roomId: data.roomId});
    }
    else{
        Http.send(ctx, data.errcode, data.errmsg);
    }
}



/**
 * 进入房间
 */
async function enter_room(ctx: Router.IRouterContext){
    const userId = parseInt(ctx.query.userId);
    const name = ctx.query.name;
    const roomId = ctx.query.roomId;
    const sign = ctx.query.sign;
    if(userId == null || roomId == null || sign == null){
        Http.send(ctx, 10, callPth + 'enter_room()->错误信息:userId == null || roomId == null || sign == null');
        return;
    }

    const signMd5 = Crypto.md5(userId + name + roomId + config.ROOM_PRI_KEY);
    if(signMd5 != sign){
        Http.send(ctx, 11, callPth + 'enter_room()->错误信息:sign验签失败');
        return;
    }

    // 安排玩家坐下
    const retMsg = await Roommgr.enterRoom(roomId, userId, name);
    if(retMsg.errcode != 0){
        Http.send(ctx, retMsg.errcode, retMsg.errmsg);
        return;
    }

    const token = TokenMgr.createToken(userId, 5000);
    Http.send(ctx, 0, 'ok', {token});
}



/**
 * 检查房间是否在运行中
 */
async function is_room_runing(ctx: Router.IRouterContext){
    const roomId = ctx.query.roomId;
    const sign = ctx.query.sign;
    if(roomId == null || sign == null){
        Http.send(ctx, 16, callPth + 'is_room_runing()->错误信息：roomId == null || sign == null');
        return;
    }

    const signMd5 = Crypto.md5(roomId + config.ROOM_PRI_KEY);
    if(signMd5 != sign){
        Http.send(ctx, 17, callPth + 'is_room_runing()->错误信息：sign验证失败');
        return;
    }

    Http.send(ctx, 0, 'ok', {runing: true});
}


































/**
 * 定时向房间管理服务器发送数据
 */
async function update(){
    if(lastTickTime + config.HTTP_TICK_TIME < Date.now()){
        lastTickTime = Date.now();
        gameServerInfo.load = Roommgr.getTotalRooms();
        const data = await Http.get(config.HALL_IP, config.HALL_PORT, httpRouterMap.RESISTER_GS, gameServerInfo);
        if(data){
            if(data.errcode != 0){
                console.log(data.errmsg);
            }
            else{
                serverIp = data.ip;
            }
        }
        else{
            lastTickTime = 0;
        }
    }
}